package com.converter.huawei.utils;

import cn.hutool.core.thread.ThreadUtil;
import com.google.common.util.concurrent.*;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

/**
 * @Program: csdn @ClassName: AsyncListenUtil @Author: huyi @Date: 2021-10-30 11:48 @Description:
 * 异步线程监听回调工具 @Version: V1.0
 */
public class AsyncListenUtil {
    public static final ExecutorService executorService =
            Executors.newFixedThreadPool(10, new CustomizableThreadFactory("LISTEN-"));
    public static final ListeningExecutorService listeningExecutorService =
            MoreExecutors.listeningDecorator(executorService);

    /**
     * 提交任务
     *
     * @param work Callable需要线程执行的内容
     * @param consumer 结果消费
     * @param errorConsumer 异常消费
     * @param <T> 泛型
     */
    public static <T> void submit(
            Callable<T> work, Consumer<T> consumer, Consumer<Throwable> errorConsumer) {
        ListenableFuture<T> listenableFuture = listeningExecutorService.submit(work);
        Futures.addCallback(
                listenableFuture,
                new FutureCallback<T>() {
                    @Override
                    public void onSuccess(@Nullable T s) {
                        consumer.accept(s);
                    }

                    @Override
                    public void onFailure(Throwable throwable) {
                        errorConsumer.accept(throwable);
                    }
                },
                listeningExecutorService);
    }

    /** 摧毁线程池 */
    public static void destroy() {
        System.out.println("摧毁线程池");
        executorService.shutdown();
    }

    public static void main(String[] args) {
        AsyncListenUtil.submit(
                () -> {
                    // todo 需要执行的内容
                    ThreadUtil.sleep(10, TimeUnit.SECONDS);
                    return "I finished my work";
                },
                result -> {
                    // todo 结果处理
                    System.out.println("listen get :" + result);
                },
                throwable -> {
                    // todo 异常处理
                    System.out.println(throwable.getMessage());
                });
        ThreadUtil.sleep(20, TimeUnit.SECONDS);
        destroy();
    }
}